#ifndef SG_GUI_H
#define SG_GUI_H

#include <MyGUI.h>
#include "Base/StatisticInfo.h"
#include "Base/InputFocusInfo.h"
#include "Input/Win32/ResourceW32Pointer.h"
#include <d3dx9.h>
#include <Windows.h>

namespace MyGUI
{
    class DirectXPlatform;
}

namespace sgGUI {

    class InputManager
    {
    public:
        InputManager();
        virtual ~InputManager();

        void createInput(size_t _handle);
        void destroyInput();
        void captureInput();
        void setInputViewSize(int _width, int _height);

        virtual void injectMouseMove(int _absx, int _absy, int _absz) { }
        virtual void injectMousePress(int _absx, int _absy, MyGUI::MouseButton _id) { }
        virtual void injectMouseRelease(int _absx, int _absy, MyGUI::MouseButton _id) { }
        virtual void injectKeyPress(MyGUI::KeyCode _key, MyGUI::Char _text) { }
        virtual void injectKeyRelease(MyGUI::KeyCode _key) { }

        virtual void onFileDrop(const std::wstring& _filename) { }
        virtual bool onWinodwClose(size_t _handle) { return true; }

        void setMousePosition(int _x, int _y);
        void updateCursorPosition();

    private:
        static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

    private:
        static InputManager* msInputManager;
        HWND mHwnd;
        static LRESULT msOldWindowProc;
        int mWidth;
        int mHeight;
        static bool msSkipMove;
    };

    class PointerManager
    {
    public:
        PointerManager();
        virtual ~PointerManager();

        void createPointerManager(size_t _handle);
        void destroyPointerManager();

        void setPointerVisible(bool _value);
        void setPointerName(const std::string& _name);

    private:
        void notifyChangeMousePointer(const std::string& _name);
        void setPointerHandle(size_t _id);
        bool isMouseInClient();
        void setPointer(const std::string& _name);

    private:
        typedef std::map<std::string, size_t> MapPointer;
        MapPointer mMapGuiPointer;
        size_t mHwnd;
        bool mManagerPointer;
    };

    class BaseManager :
        public sgGUI::InputManager,
        public sgGUI::PointerManager
    {
    public:
        BaseManager();
        virtual ~BaseManager();
        
        static BaseManager *Instance( );
        virtual void prepare();
        bool create();
        bool create( HWND hwnd );
        void destroy();
        void run();
        void quit();

        void setWindowCaption(const std::wstring& _text);
        void createDefaultScene() { }

        const std::string& getRootMedia();
        void setResourceFilename(const std::string& _flename);
        void addResourceLocation(const std::string& _name, bool _recursive = false);

        diagnostic::StatisticInfo* getStatisticInfo();
        diagnostic::InputFocusInfo* getFocusInput();

        /*internal:*/
        void _windowResized();
        void drawOneFrame();
    protected:
        virtual void createScene() { }
        virtual void destroyScene() { }

        virtual void setupResources();

        virtual void injectMouseMove(int _absx, int _absy, int _absz);
        virtual void injectMousePress(int _absx, int _absy, MyGUI::MouseButton _id);
        virtual void injectMouseRelease(int _absx, int _absy, MyGUI::MouseButton _id);
        virtual void injectKeyPress(MyGUI::KeyCode _key, MyGUI::Char _text);
        virtual void injectKeyRelease(MyGUI::KeyCode _key);

    private:
        void createGui();
        void destroyGui();

        void windowAdjustSettings(HWND hWnd, int width, int height, bool fullScreen);
        void updateFPS();

        void resizeRender(int _width, int _height);
        bool createRender(int _width, int _height, bool _windowed);
        void destroyRender();

    private:
        MyGUI::Gui* mGUI;
        MyGUI::DirectXPlatform* mPlatform;
        diagnostic::StatisticInfo* mInfo;
        diagnostic::InputFocusInfo* mFocusInfo;

        HWND hWnd;
        IDirect3D9* mD3d;
        IDirect3DDevice9* mDevice;
        D3DPRESENT_PARAMETERS mD3dpp;
        HINSTANCE hInstance;

        bool mExit;

        std::string mRootMedia;
        std::string mResourceFileName;
        bool mIsDeviceLost;
    };
}

#endif